﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Utils;
using PloobsEngine.Modelo;
using PloobsEngine.SceneControl;
using PloobsEngine.Cameras;
using PloobsEngine.Modelo.Animation;

namespace PloobsEngine.Material
{
    /// <summary>
    /// Most Basic Shader
    /// </summary>
    public class NormalDeferred : IShader
    {
        private Effect _shader;        
        EffectParameter ViewParameter;          
        EffectParameter TextureParameter;  
        EffectParameter SpecularPowerParameter;  
        EffectParameter SpecularIntensityParameter;
        EffectParameter IdParameter;  
        EffectParameter WorldParameter;  
   
        public NormalDeferred()
        {          
        }

        private float specularIntensity = 0f;    
        public float SpecularIntensity
        {
            get { return specularIntensity; }
            set { specularIntensity = value; }
        }
        private float specularPower = 0f;

        public float SpecularPower
        {
            get { return specularPower; }
            set { specularPower = value; }
        }


        public override void Serialize(System.Xml.XmlTextWriter textWriter)
        {
            SerializerHelper.SerializeBaseType<float>(specularIntensity, "SpecularIntensity", textWriter);
            SerializerHelper.SerializeBaseType<float>(specularPower, "SpecularPower", textWriter);            
            base.Serialize(textWriter);
        }

        public override void DeSerialize(System.Xml.XmlNode node, EngineStuff engine, IAnimatedController con)
        {
            specularIntensity = SerializerHelper.DeserializeBaseType<float>("SpecularIntensity", node);
            specularPower = SerializerHelper.DeserializeBaseType<float>("SpecularPower", node);
            base.DeSerialize(node, engine, con);
        }

        
        public override void Draw(IModelo modelo, IRenderHelper render, ICamera camera)
        {
           if (obj != null)
            {
                IdParameter.SetValue(shaderId);
                SpecularIntensityParameter.SetValue(specularIntensity);
                SpecularPowerParameter.SetValue(specularPower);
                TextureParameter.SetValue(modelo.getTexture(TextureType.DIFFUSE));
                ViewParameter.SetValue(camera.View * camera.Projection);

                Matrix[] boneTransforms = modelo.getBonesTransformation();
                Matrix wld = obj.getWorldMatrix();

                for (int i = 0; i < modelo.MeshNumber; i++)
                {                    
                    BatchInformation[] bi = modelo.GetBatchInformation(i);
                    Matrix w1 = Matrix.Multiply(wld, boneTransforms[modelo.GetParentBoneIndex(i)]);
                    WorldParameter.SetValue(w1);
                    for (int j = 0; j < bi.Count(); j++)
                    {
                        
                        this._shader.Begin();
                        EngineStuff.GraphicsDevice.VertexDeclaration = bi[j].VertexDeclaration;
                        EngineStuff.GraphicsDevice.Vertices[0].SetSource(modelo.GetVertexBuffer(i), bi[j].StreamOffset, bi[j].VertexStride);
                        EngineStuff.GraphicsDevice.Indices = modelo.GetIndexBuffer(i);                                                
                        
                        this._shader.CurrentTechnique.Passes[0].Begin();
                        EngineStuff.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, bi[j].BaseVertex, 0, bi[j].NumVertices, bi[j].StartIndex, bi[j].PrimitiveCount);                       
                        this._shader.CurrentTechnique.Passes[0].End();
                        this._shader.End();
                    }

                }              
            }
        }
        
        public override void Initialize()
        {            
            this._shader = EngineStuff.InternalContentManager.GetAsset<Effect>("RenderGBuffer");
            //this._shader = EngineStuff.InternalContentManager.GetAsset<Effect>("..\\Content\\Effects\\RenderGBuffer");            

            ViewParameter = this._shader.Parameters["ViewProjection"];              
            TextureParameter = this._shader.Parameters["Texture"];
            IdParameter = this._shader.Parameters["id"];
            SpecularIntensityParameter = this._shader.Parameters["specularIntensity"];
            SpecularPowerParameter = this._shader.Parameters["specularPower"];  
            WorldParameter = this._shader.Parameters["World"];  

        }

        public override MaterialType MaterialType
        {
            get { return MaterialType.DEFERRED; }
        }
    }
}
